home *** CD-ROM | disk | FTP | other *** search
- #include <stdlib.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <assert.h>
- #include <math.h>
- #ifdef __TURBOC__
- #include <mem.h>
- #include <alloc.h>
- #else
- #define farcalloc calloc
- #define farcoreleft() (1200000)
- #endif
- #ifdef unix
- #define EXIT_FAILURE 1
- #endif
-
- #include "bmp.h"
- #define CLIPSIZE ((long) PWIDTH* (long) sizeof(int)* (long) (b->ny+2))
- #define dbg if (gdebug==true)
-
- #define false 0
- #define true !0
- extern int gdebug;
- int iscolor;
- extern int dev_noclip;
-
- int row_show(char *s,Run *r,int y);
- int row_init(Run *r, int ny);
- int bmp_paintsort(int *p, int np);
- int row_free(Run *r, int ny);
- int row_grow(Run *r, int y, int v);
- int bmp_ink4(Bitmap *bb,unsigned int savem,int cindex);
- int bmp_ink16(Bitmap *bb,unsigned int newink[],int cindex);
- int bmpcheck(Bitmap *b);
-
- /*
- Filling routines to allow an arbitrary dimensioned
- bitmap to be drawn into.
- */
-
- /* General notes:
- Color and pattern are the same thing, on a
- color system the pattern array would have the
- same depth as the bitmap itself.
-
- White bit = 1;
- Black bit = 0;
- */
-
-
- /* allocates the storage required.
- initializes it
- returns NULL if not enough memory
- returns pointer to Bitmap structure
- (ignoring depth at the moment)
-
- */
-
- /* FILE *fgle; */
- Bitmap *bmp_open(int xsize,int ysize,int depth, int bmp_compress)
- {
- Bitmap *b;
- int *p;
- int i,j;
-
- /* fgle = fopen("test.gle","w");
- fprintf(fgle,"size 15 15\n");
- fprintf(fgle,"scale .3 .3 \n");
- */
- b = (Bitmap *) calloc(1,sizeof(Bitmap));
- if (b==NULL) bmp_die("No memory for Bitmap structure\n");
- b->nx = xsize;
- b->ny = ysize;
- b->compress = bmp_compress;
-
- row_init(&b->clip,b->ny);
- row_init(&b->paint,b->ny);
- row_init(&b->horiz,b->ny);
-
- b->data = (char *(*)[]) calloc(1,sizeof(int *) * (ysize+3));
- if (b->data == NULL) bmp_die("No memory for bitmap pointers \n");
-
- { long x;
- if (iscolor) x=xsize/2;
- else x=xsize/8;
- x = x*ysize+80000L;
- if (farcoreleft() < x) b->compress = true;
- }
- if (b->compress) printf("Compressing internal bitmap to save memory\n");
-
- if (b->compress==false) {
- for (i=0; i<=ysize+1; i++) {
- if (iscolor) {
- if ( ((*b->data)[i] = calloc(1,xsize/2+2)) == NULL)
- bmp_die("No memory for bitmap\n");
- memset( (*b->data)[i], 255, xsize/2+2);
- } else {
- if ( ((*b->data)[i] = calloc(1,xsize/8+2)) == NULL)
- bmp_die("No memory for bitmap\n");
- memset( (*b->data)[i], 255, xsize/8+2);
- }
- }
- }
- b->painty1 = ysize;
- b->lwidth = 1;
- b->lstyle = 0x8000001e;
- b->lstyle_mask = 0x80000000;
- b->lstyle_dotlen = 1;
- b->lstyle_dotpix = 0;
- bmp_color(b,0);
- #ifdef __TURBOC__
- /* printf("Free memory after bitmap allocated %ld \n",farcoreleft()); */
- #endif
- return b;
- }
- row_init(Run *r, int ny)
- {
- r->alloc = (unsigned char *) calloc(1,ny+3);
- if (r->alloc == NULL) bmp_die("Not enough memory for run counts \n");
- r->used = (unsigned char *) calloc(1,ny+3);
- if (r->used == NULL) bmp_die("Not enough memory for run counts \n");
- r->row = (typrow) calloc(sizeof(int *),ny+3);
- if (r->row == NULL) bmp_die("Not enough memory for run counts \n");
- }
- row_free(Run *r, int ny)
- {
- int i,*rr;
- for (i=0;i<=ny;i++) {
- rr = (*r->row)[i];
- if (rr!=NULL) free(rr);
- }
- free(r->row);
- free(r->used);
- free(r->alloc);
- }
- int row_shrinkx(Run *r, int ny);
- int row_shrink(Bitmap *b);
- row_shrink(Bitmap *b)
- {
- row_shrinkx(&b->paint,b->ny);
- row_shrinkx(&b->horiz,b->ny);
- }
- row_shrinkx(Run *r, int ny)
- {
- int i,*rr;
- for (i=0;i<=ny;i++) {
- rr = (*r->row)[i];
- if (rr!=NULL) free(rr);
- (*r->row)[i] = NULL;
- r->used[i] = 0;
- r->alloc[i] = 0;
- }
- }
- #define row_data(r,y) ( (*r.row)[y] )
- #define row_used(r,y) ( r.used[y] )
- #define row_setused(r,y,v) ( r.used[y] = v )
- row_grow(Run *r, int y, int v)
- {
- int vv;
- int *z;
- v += r->used[y];
- if (v<= r->alloc[y]) {
- r->used[y] = v;
- return;
- }
- vv = v;
- if ((v&1)==1) vv++;
- z = (*r->row)[y] ;
- if (z==NULL) z = (int *) malloc(vv*sizeof(int));
- else z = (int *) realloc((*r->row)[y],vv*sizeof(int));
- /*
- if (z==NULL) z = malloc(vv*sizeof(int));
- else {
- z = malloc(vv*sizeof(int));
- memcpy(z, (*r->row)[y] ,r->used[y]*sizeof(int));
- free( (*r->row)[y] );
- }
- */
- (*r->row)[y] = z;
- /* malloc(v); */
- if ((*r->row)[y] == NULL) bmp_die("Could not grow row count data \n");
- r->alloc[y] = vv;
- r->used[y] = v;
- }
-
- /* frees up all storage. */
- iffree(void *block)
- {
- if (block!=NULL) free(block);
- }
- bmp_close(Bitmap *b)
- {
- int i,j;
- if (b==NULL) return;
- for (i=0; i<=b->ny+2; i++) {
- iffree((*b->data)[i]);
- }
- row_free(&b->paint,b->ny);
- row_free(&b->clip,b->ny);
- row_free(&b->horiz,b->ny);
- /* fclose(fgle); */
- }
-
- /*
- Draws line of current lwidth, lstyle,
- and color/pattern
-
- Line is clipped using clip array.
- */
- #define sign(x) ((x) > 0 ? 1: ((x) == 0 ? 0: (-1)))
- bmp_line(Bitmap *b,int x1,int y1,int x2,int y2)
- {
- int dx, dy, dxabs, dyabs, i, j, px, py, sdx, sdy;
- register int x,y;
- unsigned long int mask,pattern,lastpatbit;
- int lwidth, dotlen,pix;
-
- lwidth = b->lwidth/2;
- mask = b->lstyle_mask;
- pattern = b->lstyle;
- lastpatbit = 1l << (pattern & 0x1f);
- dotlen = b->lstyle_dotlen;
- pix = b->lstyle_dotpix;
-
- /* printf("lstyle %08lx, mask %08lx, dotlen %d, dotpix %d, lastpatbit %8lx pat= %lx \n",
- pattern,mask,dotlen,pix,lastpatbit,pattern & 0x1f);
- */
- if (bmp_clipline(b,&x1,&y1,&x2,&y2)) return; /* clip to bitmap */
- dx = x2 - x1;
- dy = y2 - y1;
- sdx = sign(dx);
- sdy = sign(dy);
- dxabs = abs(dx);
- dyabs = abs(dy);
- x = 0;
- y = 0;
- px = x1;
- py = y1;
-
- if (dxabs >= dyabs) {
- mask = (mask & lastpatbit) ? 0x80000000 : mask;
- if (pattern & mask) {
- for (j= -lwidth; j<=lwidth; j++)
- bmp_pixel(b,px,py+j);
- }
- if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
- for (i=0; i<dxabs; i++) {
- mask = (mask & lastpatbit) ? 0x80000000 : mask;
- y += dyabs;
- if (y>=dxabs) {
- y -= dxabs;
- py += sdy;
- }
- px += sdx;
- if (pattern & mask) {
- for (j= -lwidth; j<=lwidth; j++)
- bmp_pixel(b,px,py+j);
- }
- if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
- }
- } else {
- mask = (mask & lastpatbit) ? 0x80000000 : mask;
- if (pattern & mask) {
- for (j= -lwidth; j<=lwidth; j++)
- bmp_pixel(b,px+j,py);
- }
- if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
- for (i=0; i<dyabs; i++) {
- mask = (mask & lastpatbit) ? 0x80000000 : mask;
- x += dxabs;
- if (x>=dyabs) {
- x -= dyabs;
- px += sdx;
- }
- py += sdy;
- if (pattern & mask) {
- for (j= -lwidth; j<=lwidth; j++)
- bmp_pixel(b,px+j,py);
- }
- if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
- }
- }
-
- b->lstyle_mask = mask;
- b->lstyle_dotpix = pix;
- /* printf("lstyle %08x, mask %08x, lastpatbix %08x, dotpix %d \n",
- pattern, mask, lastpatbit, pix); */
-
- }
-
- /*
- Apply clipping
- Get bit from ink
- Get row of bitmap
- Place bit into row
- */
- static Bitmap *pr_lb;
- static int pr_ly;
- static char *pr_row;
- bmp_pixel(register Bitmap *b,register int x,register int y)
- {
- static int i,spot;
- int ry;
- /* static char *row; */
- unsigned char *k;
-
- if (b->clipping) if (bmp_invis(b,x,y)) return;
- if (x> b->nx || x<0 || y>b->ny || y<0) return;
- ry = y % 16;
- if (pr_ly!=y || pr_lb!=b) {
- pr_row = bmp_row(b,y);
- pr_ly = y; pr_lb = b;
- }
-
- k = (unsigned char *) &b->ink[ry%16][0];
- spot = k[x%16];
- if (iscolor) {
- i = pr_row[x/2];
- if (x % 2==0) {
- i = (i & 0x0f) | (spot << 4);
- } else {
- i = (i & 0xf0) | spot;
- }
- pr_row[x/2] = i;
- return;
- }
-
-
- if (k[x % 16] != 0) { /* a white spot */
- *(pr_row + x/8) |= (1 << (x%8));
- } else {
- *(pr_row + x/8) &= (255-(1 << (x%8)));
- }
- }
- bmp_paintrange(Bitmap *b,int y, register int x1, int x2)
- {
- static int i,spot;
- int ry;
- /* static char *p;*/
- unsigned char *k;
-
- /* debugging stuff */
- if (x1==-2 || x2==-2) {
- printf("********Stuffed range on line %d, %d-->%d \n",y,x1,x2);
- return;
- }
- dbg printf("Paint range %d, %d %d \n",y,x1,x2);
-
- /* end debug */
- /* printf("Paint range %d, %d %d \n",y,x1,x2);*/
- ry = y % 16;
- if (pr_ly!=y || pr_lb!=b) {
- pr_row = bmp_row(b,y);
- pr_ly = y; pr_lb = b;
- }
-
-
- k = (unsigned char *) &b->ink[ry%16][0];
-
- if (iscolor) {
- for (;x1<=x2;x1++) {
- spot = k[x1%16];
- i = pr_row[x1/2];
- if (x1 % 2==0) {
- i = (i & 0x0f) | (spot << 4);
- } else {
- i = (i & 0xf0) | spot;
- }
- pr_row[x1/2] = i;
- }
- return;
- }
-
- for (;x1<=x2;x1++) {
- if (k[x1 % 16] != 0) { /* a white spot */
- *(pr_row + x1/8) |= (1 << (x1%8));
- } else {
- *(pr_row + x1/8) &= (255-(1 << (x1%8)));
- }
- }
- }
-
- /* return true if pixel at that
- location is clipped
- */
- int bmp_invis(Bitmap *b, int x, int y)
- {
- int *c,nc,i;
-
- if (! b->clipping) return false; /* clipping os off */
- c = row_data(b->clip,y);
- if (*c==0) return true; /* clipping */
- nc = row_used(b->clip,y);
- for (i=0;i<nc-1;i+=2, c+=2) {
- if ( (x>= *c) && (x<= *(c+1))) return false; /* is visible */
- }
- return true;
- }
-
- /*
- Adds x values at y crossings onto the paint[] array.
- Doesn't add last crossing
- Sets maxy,miny
-
- Special cases:
-
- move
- init lddy
- sx,sy, x1,y1 ...
-
- * Change in sdy
- put in double x value
- * When end of line meets start of line.
- remember start of line with bmp_pmove
- remember start sdy
- if sdy == enddy then don't put endx,endy
- start new polygon.
- (at fill check lines is closed, if not then close before fill)
- * (WRONG) Start of Horizontal lines
- put in start xvalue, (if not first line in path)
- * Continued horizontal line
- do nothing
- * (WRONG) end of horizontal line
- Put in last x(thisy) value
-
- * with horizontal lines or lines which have multiple x values
- store the range of values into b->horiz[][] so they can
- also be drawn in. This gets the middle of an H or A or top
- of a B drawn correctly if the bar is very thin.
- */
- bmp_pmove(Bitmap *b,int x1,int y1)
- {
- bmp_clipline(b,&x1,&y1,&x1,&y1); /* clip to bitmap */
- /* fprintf(fgle,"amove %d %d \n",x1,y1); */
- if (b->sx != b->x1 || b->sy != b->y1) {
- printf("Closing path\n");
- bmp_pline(b,b->sx,b->sy);
- }
- /* printf("pmove %d %d \n",x1,y1); */
- b->sx = x1; b->sy = y1;
- b->x1 = x1; b->y1 = y1;
- b->sddy = -2;
- b->lddy = -2;
- }
- bmp_pline(Bitmap *b,int x2,int y2)
- {
- int dx, dy, dxabs, dyabs, i, j, px, py, sdx, sdy;
- int endy,xwid;
- register int x,y;
- int x1=b->x1, y1=b->y1; /* start of line */
- int lddy=b->lddy;
- int ddy,horizx;
-
- if (x1==x2 && y1==y2) return; /* not going anywhere */
-
-
-
- if (bmp_clipline(b,&x1,&y1,&x2,&y2)) return; /* clip to bitmap */
- /* fprintf(fgle,"aline %d %d \n",x2,y2);
- printf("CVector %d,%d --- %d,%d \n",x1,y1,x2,y2);
- */
- b->x1 = x2; b->y1 = y2; /* remember end of line */
- bmp_minmax(b,y1);
- bmp_minmax(b,y2); /* remember range of y paint values */
-
- dx = x2 - x1;
- dy = y2 - y1;
- xwid = dx/2;
- sdx = sign(dx);
- sdy = sign(dy);
- dxabs = abs(dx);
- dyabs = abs(dy);
- x = 0;
- y = 0;
- px = x1;
- py = y1;
- endy = y2;
-
- ddy = sdy;
- if (dy==0) ddy = 0; /* ddy = -1, 0, 1 */
- if (ddy==0) { /* this is a horizontal line */
- bmp_painth(b,x1,x2,y1); /* paint the whole line */
- goto endpline;
- }
- if (lddy == -ddy) bmp_paintx(b,x1,y1); /* put in last endxy */
- if (dxabs >= dyabs) {
- horizx = px+sdx; /* start of first row */
- for (i=0; i<dxabs; i++) {
- y += dyabs;
- if (y>=dxabs) {
- y -= dxabs;
- bmp_painth(b,horizx,px,py); /* end of that row */
- py += sdy;
- horizx = px+sdx; /* start of next row */
- /* if (py==endy) break; */
- bmp_paintx(b,px+sdx,py);
- }
- px += sdx;
- }
- } else {
- for (i=0; i<dyabs; i++) {
- x += dxabs;
- if (x>=dyabs) {
- x -= dyabs;
- px += sdx;
- }
- py += sdy;
- bmp_paintx(b,px,py);
- }
- }
-
- endpline:
- if (ddy!=0) { /* remember last line if not horiz */
- b->lddy = ddy;
- if (lddy== -2) { /* first line */
- b->sddy = ddy;
- b->ssx = x1;
- b->ssy = y1;
- return;
- }
- }
-
- if (x2==b->sx && y2==b->sy) { /* path is closed */
- if (b->sddy == -b->lddy) { /* direction changed */
- bmp_paintx(b,b->ssx,b->ssy);
- }
- }
- }
-
- bmp_minmax(Bitmap *b,int y) /* remember range of y paint values */
- {
- if (y<b->painty1) b->painty1 = y;
- if (y>b->painty2) b->painty2 = y;
- }
-
- /*
- Adds x value onto paint[] range table
- */
- bmpcheck(Bitmap *b)
- {
- int i,*p;
-
- for (i=0;i<16;i++) {
- /* p = &(*b->paint)[i][0];
- printf("P[%d] = %d %d %d %d \n",i,*p,*(p+1),*(p+2),*(p+3));
- */
- }
- }
- bmp_paintx(Bitmap *b, int x, int y)
- {
- int *c,nc,i,nrow;
-
-
- i = 0;
- row_grow(&b->paint,y,1);
- c = row_data(b->paint,y);
- c += row_used(b->paint,y) - 1;
- *c = x;
-
- c = row_data(b->paint,y);
- nc = row_used(b->paint,y);
- /*
- printf("Paint [%d] x=%d , ",y,x);
- for (i=0;i<nc;i++,c++) {
- printf("%d ",*c);
- }
- printf("\n");
- */
- }
- row_show(char *s,Run *r,int y)
- {
- int i,*c,nc;
-
- c = (*r->row)[y];
- nc = r->used[y];
- printf("show {%s} [%d] ",s,y);
- for (i=0;i<nc;i++,c++) {
- printf("%d ",*c);
- }
- printf("\n");
- }
- /*
- This routine remembers the horizontal lines that
- need to be drawn.
-
- They don't need sorting, and they can be amalgamated e.g.
- They do need putting into ascending order when used.
-
- 1 7, 5 9, can become 1 9
- */
- showhy(Bitmap *b, int y)
- {
- int *c,i;
-
- i = 0;
- /* c = &(*b->horiz)[y][0];
- c = (*b->horiz.row)[y];
- printf("showy ");
- for (;i < (*b->horiz.used)[y];c+=2 ,i+=2) {
- printf("%d %d ",*c,*(c+1));
- }
- printf("\n");
- */
- }
- bmp_painth(Bitmap *b, int x1,int x2, int y)
- {
- int *c,i,nc;
-
- /* printf("Addh, (%d) %d %d \n",y,x1,x2); */
-
- if (x1>x2) {i=x2; x2=x1; x1=i;}
- i = 0;
- c = row_data(b->horiz,y);
- nc = row_used(b->horiz,y);
- for (;i < nc-1 ;c+=2 ,i+=2) {
- if (*c<=x1 && *(c+1)>=x1) {
- c++;
- if (*c < x2) *c = x2;
- return;
- }
- if (*c<=x2 && *(c+1)>=x2) {
- if (*c > x1) *c = x1;
- return;
- }
- if (*c-1 == x2) { *c = x1; return;}
- if (*(c+1)+1 == x1) { *(c+1) = x2; return;}
- }
- /* found an empty slot */
-
- row_grow(&b->horiz,y,2); /* make it two bigger */
- c = row_data(b->horiz,y);
- nc = row_used(b->horiz,y);
- c += nc - 2;
- *c = x1;
- *(c+1) = x2;
- }
-
- /* Clear the current path. */
- bmp_newpath(Bitmap *b)
- {
- int i,j;
- int *c;
-
- for (i=b->painty1; i<=b->painty2; i++) {
- row_setused(b->paint,i,0);
- row_setused(b->horiz,i,0);
- }
- b->painty1 = b->ny+2;
- b->painty2 = 0;
-
- if (farcoreleft()<50000L) row_shrink(b);
- }
-
- /*
- from painty1 to painty2
- sort x's and call bmp_paint(b,y,x1,x2);
- */
- bmp_paintsort(int *p, int np)
- {
- int *pp = p;
- int a,b,fixed,i;
-
- fixed = true;
- for (;fixed;) {
- fixed = false;
- for (p = pp, i = 0; i<(np-1); i++, p++) {
- if (*p > *(p+1)) {
- a = *p;
- *p = *(p+1);
- *(p+1) = a;
- fixed=true;
- }
- }
- }
- p = pp;
- /*
- printf("(sort) ");
- for (;*p!=-2;p++) printf("%d ",*p);
- printf("\n");
- */}
-
-
- bmp_fill(Bitmap *b)
- {
- int i,k,nrow,ncrow,j,x1,x2;
- int *c,*p,np,nc;
-
- /* printf ("Fill, color is %d \n",b->ink[0][0]); */
- if (b->sx != b->x1 || b->sy != b->y1) {
- printf("Closing path\n");
- bmp_pline(b,b->sx,b->sy);
- }
- for (i=b->painty1; i<=b->painty2; i++) {
- p = row_data(b->paint,i);
- np = row_used(b->paint,i);
- bmp_paintsort(p,np);
- for (j=0;j<np-1; j+=2, p+=2) {
- c = row_data(b->clip,i);
- nc = row_used(b->clip,i);
- if (!b->clipping) bmp_paintrange(b,i,*p,*(p+1)); /* no clipping */
- else {
- for (k=0;k<nc-1; k+=2, c+=2) {
- x1 = *p; x2 = *(p+1);
- if (x1< *c) x1 = *c;
- if (x2> *(c+1)) x2 = *(c+1);
- if (x1<=x2) bmp_paintrange(b,i,x1,x2); /* clipped range */
- }
- }
- }
-
- /* now paint the thin horizontal bits */
- p = row_data(b->horiz,i);
- np = row_used(b->horiz,i);
- for (j=0;j<np-1; j+=2, p+=2) {
- if (!b->clipping) bmp_paintrange(b,i,*p,*(p+1)); /* no clipping */
- else {
- c = row_data(b->clip,i);
- nc = row_used(b->clip,i);
- for (k=0;k<nc-1; k+=2, c+=2) {
- x1 = *p; x2 = *(p+1);
- if (x1< *c) x1 = *c;
- if (x2> *(c+1)) x2 = *(c+1);
- if (x1<=x2) bmp_paintrange(b,i,x1,x2); /* clipped range */
- }
- }
- }
- /* end horizontal bits */
- }
- }
-
-
-
- /* Coppies bitmap on while applying clip (not using ink[])
- */
- /*
- bmp_copy(Bitmap *b,char *bitmap,int nx,int ny)
- {
- }
- */
- /* Move paint array onto clip array. */
- bmp_clip(Bitmap *b)
- {
- int i;
- int *c,*p,nc;
-
- if (dev_noclip) return;
-
- /* Sort the paint array before copying it */
- for (i=0;i<b->ny; i++) {
- c = row_data(b->paint,i);
- bmp_paintsort(c,row_used(b->paint,i));
- }
-
- /* Now simply copy it over */
- for (i=0;i<b->ny; i++) {
- p = row_data(b->paint,i);
- nc = row_used(b->paint,i);
-
- if (nc>0) {
- row_grow(&b->clip,i,nc);
- c = row_data(b->clip,i);
- memcpy(c,p,nc*sizeof(int));
- }
-
- }
-
- b->clipping = true; /* remeber that clipping is on now */
- }
-
- /* Clears the clipping array */
- bmp_newclip(Bitmap *b)
- {
- int i,j;
- int *c;
-
- if (dev_noclip) return;
- b->clipping = false;
- for (i=0; i<=b->ny+1; i++) {
- row_setused(b->clip,i,0);
- }
- }
-
- /*
- Coppies clipping array and lastclip pointer into malloced area
- and sets lastclip to point to this new malloced area.
- */
- bmp_saveclip(Bitmap *b)
- {
- int *c;
-
- if (dev_noclip) return;
- /* should save clipping region */
- }
-
- bmp_restoreclip(Bitmap *b)
- {
- int *c;
- if (dev_noclip) return;
- /* should restore from saved memory but I'm in a hurry */
- b->clipping = false;
-
- #ifdef __TURBOC__
- row_shrinkx(&b->clip,b->ny);
- #endif
- }
-
- /* Sets ink based on a lookup table
- 255 = white, 0 = black
- */
- bmp_color(Bitmap *b,int colindex)
- {
- int i,j;
- for (i=0;i<16;i++)
- for (j=0;j<16;j++)
- b->ink[i][j] = colindex;
- }
-
-
- unsigned int grey_bits[] = {0x0000, 0x0200, 0x0802, 0x0a02,
- 0x5050, 0x5250, 0x5852, 0x5a52,
- 0xa5a5, 0xa7a5, 0xada7, 0xafa7,
- 0xf5f5, 0xf7f5, 0xfdf7, 0xfff7, 0xffff};
-
-
- static unsigned int pat_shade1[] = {
- 0xc000, 0x6000, 0x3000, 0x1800, 0xc00, 0x600, 0x300,
- 0x180, 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3, 0x8001 };
- static unsigned int pat_shade2[] = {
- 0xc018, 0x600c, 0x3006, 0x1803, 0x8c01, 0xc600, 0x6300, 0x3180,
- 0x18c0, 0xc60, 0x630, 0x318, 0x18c, 0xc6, 0x63, 0x8031 };
- static unsigned int pat_shade3[] = {
- 0xf078, 0x783c, 0x3c1e, 0x1e0f, 0x8f07, 0xc783, 0xe3c1, 0xf1e0,
- 0x78f0, 0x3c78, 0x1e3c, 0xf1e, 0x78f, 0x83c7, 0xc1e3, 0xe0f1 };
- static unsigned int pat_shade4[] = {
- 0x7e00, 0x3f00, 0x1f80, 0xfc0, 0x7e0, 0x3f0, 0x1f8, 0xfc,
- 0x7e, 0x3f, 0x801f, 0xc00f, 0xe007, 0xf003, 0xf801, 0xfc00 };
- static unsigned int pat_shade5[] = {
- 0x6006, 0x7ffe,0x6006,0x300c,0x1818,0xc30, 0x660, 0x3c0,
- 0x660, 0xc30, 0x1998,0x33cc,0x67e6,0x7ffe,0x6006, 0x6006 };
- static unsigned int pat_grid1[] = {
- 0xc003, 0x6006, 0x300c, 0x1818, 0xc30, 0x660, 0x3c0, 0x180,
- 0x3c0, 0x660, 0xc30, 0x1818, 0x300c, 0x6006, 0xc003, 0x8001 };
- static unsigned int pat_grid2[] = {
- 0xf00f, 0x781e, 0x3c3c, 0x1e78, 0xff0, 0xfe0, 0xfc0, 0xf80,
- 0xfc0, 0xfe0, 0xff0, 0x1e78, 0x3c3c, 0x781e, 0xf00f, 0xf00f };
- static unsigned int pat_grid3[] = {
- 0xffff, 0xffff, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0xffff,
- 0xffff, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0xffff, 0xffff};
- static unsigned int pat_grid4[] = {
- 0x303, 0x303, 0xcfc0, 0xcfc0, 0x3ff0, 0x3ff0, 0xfcc, 0xfcc,
- 0x303, 0x303, 0xcc0f, 0xcc0f, 0xf03f, 0xf03f, 0xc0cf, 0xc0cf };
- static unsigned int pat_grid5[] = {
- 0x300, 0x300, 0x300, 0x300, 0xcc0, 0xcc0, 0xf03f, 0xf03f,
- 0x3, 0x3, 0x3, 0x3, 0xc00c, 0xc00c, 0x3ff0, 0x3ff0 };
-
-
- #define NGREY 17
- bmp_setcolor(Bitmap *bb,int r, int g, int b, int ftyp)
- {
- /* values between 0-255 */
- unsigned int i,j,m,nib,k,n,xx,savenib,ix,iy,savem;
- unsigned int *patt;
- int cindex;
- float f;
-
- f = (r*3+g*2+b)/(255*6.0);
-
- i = (1-f)*(NGREY-.8);
- if (f<1 && i==0) i = 1;
-
- savem = grey_bits[i];
-
- /* Fill types,
- 2=pat_black, 3=pat_red, 4=pat_green,
- 5=pat_blue, 6=pat_yellow
- */
-
- if (ftyp>1 && ftyp<7) {
- cindex = 0;
- if (ftyp==3) cindex = 1;
- if (ftyp==4) cindex = 2;
- if (ftyp==5) cindex = 4;
- if (ftyp==6) cindex = 3;
- if (!iscolor) cindex = 0;
- if (g==0x0 && b==0x20) patt = pat_shade1;
- if (g==0x0 && b==0x0c) patt = pat_shade1;
- if (g==0x0 && b==0x10) patt = pat_shade2;
- if (r==0x5 && b==0x20) patt = pat_shade3;
- if (g==0x0 && b==0x40) patt = pat_shade4;
- if (g==0x0 && b==0x60) patt = pat_shade5;
- if (g==0x20 && b==0x20) patt = pat_grid1;
- if (g==0xf && b==0xf) patt = pat_grid1;
- if (g==0x10 && b==0x10) patt = pat_grid2;
- if (g==0x20 && b==0x20) patt = pat_grid3;
- if (g==0x40 && b==0x40) patt = pat_grid4;
- if (g==0x60 && b==0x60) patt = pat_grid5;
- bmp_ink16(bb,patt,cindex);
- return;
- }
- /* 0 = black, 1=red, green, blue, yellow, magenta, brown, ... white */
-
- if (r==g && g==b) {
- bmp_ink4(bb,savem,0);
- return;
- }
- if (iscolor) {
- cindex = -1;
- if (r>20 && g==0 && b==0) {cindex = 1; f=r;}
- if (g>20 && r==0 && b==0) {cindex = 2; f=g;}
- if (b>20 && g==0 && r==0) {cindex = 4; f=b;}
- if (r>20 && g>20 && b==0) {cindex = 3; f=r;}
- if (cindex>=0) {
- f = f/255.0;
- i = (f)*(NGREY-.8);
- if (f<1 && i==(NGREY-1)) i = NGREY-2;
- bmp_ink4(bb,grey_bits[i],cindex);
- return;
- }
- if (r>150 && g<50 && b<50) cindex = 1;
- if (r<50 && g>150 && b<50) cindex = 2;
- if (r<50 && g<50 && b>150) cindex = 4;
- if (r>150 && g>150 && b<50) cindex = 3;
- if (b>50 && g>50 && r<18) cindex = 6; /* CYAN */
- if (r>50 && b>50 && g<20) cindex = 5; /* Magenta */
- if (cindex >= 0) {
- bmp_color(bb,cindex);
- return;
- }
- }
- bmp_ink4(bb,savem,0);
- }
- bmp_ink4(Bitmap *bb,unsigned int savem,int cindex)
- {
- /* values between 0-255 */
- unsigned int i,j,m,nib,k,n,xx,savenib,ix,iy;
- unsigned int *patt;
- float f;
-
- for (ix=0; ix<16; ix+=4) {
- for (iy=0; iy<16; iy+=4) {
- m = savem;
- for (j=0; j<4; j++) {
- nib = m & 0xf;
- for (k=0; k<4; k++) {
- if (nib&1) bb->ink[ix+j][iy+k] = cindex;
- else bb->ink[ix+j][iy+k] = 15;
- nib = nib >> 1;
- }
- m = m >> 4;
- }
- }
- }
-
- }
- bmp_ink16(Bitmap *bb,unsigned int newink[],int cindex)
- {
- unsigned int m;
- int i,ix,iy;
-
- for (iy=0; iy<16; iy++) {
- m = newink[iy];
- for (ix=15; ix>=0; ix--) {
- if (m&1 == 1) bb->ink[iy][ix] = cindex;
- else bb->ink[iy][ix] = 15;
- /* printf("ix iy %d %d %d\n",ix,iy,bb->ink[ix][iy]);
- */ m = m >> 1;
- }
- }
- }
- bmp_lwidth(Bitmap *b,int x)
- {
- b->lwidth = x;
- }
-
- bmp_lstyle(Bitmap *b,long n,int l)
- /* n is a pattern, 01110001110; l is len of one pattern dot in pixels */
- {
- b->lstyle = n;
- b->lstyle_mask = 0x80000000;
- b->lstyle_dotlen = l;
- b->lstyle_dotpix = 0;
- }
-
- /* (depth must be 1, expands this into the pat[][] array,
- each 1 becomes a 255)
- */
- /*
- bmp_pattern(Bitmap *b,char *pat,int nxbytes,int nybytes,int depth)
- {
- }
- */
- /* Returns pointer to a row of the bitmap */
-
- unsigned char *bmp_expanded(Bitmap *b,int y);
- char *bmp_row(Bitmap *b,int y)
- {
- pr_ly = -1;
- if (b->compress) {
- return (char *) bmp_expanded(b,y);
- } else {
- return (*b->data)[y];
- }
- }
- /* this compression routine won't work with more than one 'Bitmap' as
- it doesn't store it's data in Bitmap *b, like it should. */
-
- unsigned char *bmp_expanded(Bitmap *b,int y)
- {
- static unsigned char *bitrow,*bitc;
- static unsigned char *o,*bc,c,*lastv;
- static int lasty = -2;
- char *v;
- int nc,x,i,j,nxbyte;
- int totwid = 0;
-
-
- if (lasty==y) return bitrow;
- nxbyte = b->nx/8+1;
- if (iscolor) nxbyte = b->nx/2+2;
- if (bitrow==NULL) bitrow = (ucharp) calloc(1,nxbyte+3);
- if (bitc == NULL) bitc = (ucharp) calloc(1,nxbyte*2+3);
- if (bitrow==NULL || bitc==NULL) bmp_die("bitc allocation error\n");
- v = (*b->data)[y];
-
- if (lasty != -2) {
- o = bitc;
- /* if (lasty==296) {
- printf("Store [%d]",lasty);
- for (i=0;i<nxbyte;i++) printf("%x ",bitrow[i]);
- printf("\n");
- }
- */
- for (x=0; x<nxbyte ; x++) {
- c = bitrow[x];
- nc = 1;
- for (;x<(nxbyte-1) && bitrow[x+1]==c && nc<250; x++) nc++;
- *o++ = nc;
- *o++ = c;
- totwid = totwid + 2;
- }
- if (totwid>nxbyte*2) printf("Total width %d nx=%d\n",totwid,nxbyte);
- *o++ = 0;
- *o++ = 0; /* nulls at end */
- nc = o-bitc+1;
-
-
- if (lastv!=NULL) lastv = (unsigned char *) realloc(lastv,nc);
- else lastv = (ucharp) malloc(nc);
- if (lastv==NULL) {
- printf("Failed to allocate enough memory for bitmap \n");
- abort();
- }
- memcpy(lastv,bitc,nc);
- (*b->data)[lasty] = (char *) lastv;
- }
- lasty = y;
- lastv = (ucharp) v;
-
- nc = 0;
- if (v==NULL) {
- memset(bitrow,255,nxbyte);
- return bitrow;
- }
-
- nc = 0;
- bc = (ucharp) v;
-
- for (i=0, o = bitrow; bc[i]!=0 ; i+=2) {
- for (j=0; j<bc[i]; j++) {
- *o++ = bc[i+1]; nc++;
- if (nc>nxbyte) {
-
- printf("ERR[%d] ",y);
- for (i=0;bc[i]!=0;i+=2) printf("%d,%x ",bc[i],bc[i+1]);
- printf("\n");
-
-
- printf("gone past end [%d] %d %d \n",y,nxbyte,nc);
- return bitrow;
- }
- }
- }
- /*
- if (y==296) {
- printf("EXP[%d] ",y); for (i=0;i<10;i++) printf("%d ",bitrow[i]);
- printf("\n");
- }
- */
- return bitrow;
- }
- bmp_die(char *s)
- {
- printf("%s",s);
- exit(EXIT_FAILURE);
- }
-
- bmp_pbezier(Bitmap *bb,int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
- {
- float ax,bx,cx,ay,by,cy,xxx,yyy,t,nstep;
- int dist,i;
-
-
-
- dbg printf("pbezier, %d %d %d %d %d %d %d %d \n",x0,y0,x1,y1,x2,y2,x3,y3);
- dist = abs(x3-x0) + abs(y3-y0);
- nstep = 20;
- if (dist<30) nstep = 10;
- if (dist<10) nstep = 5;
- if (dist<5) nstep = 3;
- if (dist<=2) {
- bmp_pline(bb,x3,y3);
- return;
- }
- cx = (x1-x0)*3;
- bx = (x2-x1)*3-cx;
- ax = x3-x0-cx-bx;
- cy = (y1-y0)*3;
- by = (y2-y1)*3-cy;
- ay = y3-y0-cy-by;
- for (i=0;i<=nstep;i++) {
- t = (float) i/nstep;
- xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
- yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
- bmp_pline(bb,(int) xxx,(int) yyy);
- }
- }
- bmp_bezier(Bitmap *bb,int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
- {
- float ax,bx,cx,ay,by,cy,xxx,yyy,t,nstep,xx,yy;
- int dist,i;
-
- dist = abs(x3-x0) + abs(y3-y0);
- nstep = 20;
- if (dist<30) nstep = 10;
- if (dist<10) nstep = 5;
- if (dist<5) nstep = 3;
- if (dist<=2) {
- bmp_line(bb,x0,y0,x3,y3);
- return;
- }
- cx = (x1-x0)*3;
- bx = (x2-x1)*3-cx;
- ax = x3-x0-cx-bx;
- cy = (y1-y0)*3;
- by = (y2-y1)*3-cy;
- ay = y3-y0-cy-by;
- xx = x0; yy = y0;
- for (i=0;i<=nstep;i++) {
- t = (float) i/nstep;
- xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
- yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
- bmp_line(bb,(int) xx,(int) yy, (int) xxx, (int) yyy);
- xx = xxx; yy = yyy;
- }
- }
-
- #define OUTCODES_CSD( X, Y, OUTCODE ) \
- ( OUTCODE ) = 0; \
- if ((Y) >= b->ny ) OUTCODE |= 1; \
- else if ((Y) < 0 ) OUTCODE |= 2; \
- if ((X) >= b->nx ) OUTCODE |= 4; \
- else if ((X) < 0 ) OUTCODE |= 8;
-
- int bmp_clipline(Bitmap *b,int *x1, int *y1, int *x2, int *y2)
- {
- int outcode1,outcode2;
-
- OUTCODES_CSD( *x2, *y2, outcode2 );
- OUTCODES_CSD( *x1, *y1, outcode1 );
-
- if (outcode1 & outcode2) /* trivial reject */
- return true; /* throw line away */
- if (!(outcode2 | outcode1)) /* trivial accept */
- return false;
-
- doclip(0,b->nx-1,x1);
- doclip(0,b->nx-1,x2);
- doclip(0,b->ny-1,y1);
- doclip(0,b->ny-1,y2);
- return false;
- }
- doclip(int min, int max, int *v)
- {
- if (*v < min) *v = min;
- if (*v > max) *v = max;
- }
-
- showfree()
- {
- #ifdef __TURBOC__
- struct farheapinfo hi;
- long total=0;
-
- hi.ptr = NULL;
- while( farheapwalk( &hi ) == _HEAPOK ) {
- if (!hi.in_use) total += hi.size;
- }
- printf("Total mem free %ld \n",total);
- #endif
- }
-
-